/* gs_main_window.c -- Interface gráfica
 *
 * Copyright (C) 2008, Diogo F. S. Ramos <diogo.ramos@usp.br>
 * GEAR - Grupo de Estudos Avançados em Robótica
 * <http://www.sel.eesc.usp.br/gear>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <stdlib.h>
#include <glade/glade.h>
#include <gtk/gtk.h>

#include "config.h"
#include "xerror.h"
#include "xmalloc.h"
#include "gs_main_window.h"
#include "gs_utils.h"

/* Internal Signals */
/* Callbacks */
enum gs_main_window_buttons
{
    TB_DRIBBLE,
    BT_KICK,
    TB_CONNECT,
    MI_QUIT,
    MI_ABOUT,
    BT_UP,
    BT_DOWN,
    BT_TURN_LEFT,
    BT_TURN_RIGHT,
    BT_STOP
};

/* Static */
static gint std_delete_event_handler (GtkWidget   *widget, GdkEventAny *event, gpointer user_data);
static void gs_main_window_quit( gs_main_window_t * self );
static void std_button_handler( GtkButton *button, gpointer user_data );

gs_main_window_t *
gs_main_window_new( const char * argv )
{
    gs_main_window_t * self = NULL;
    GladeXML *builder = NULL;
    GtkMenuItem *action1 = NULL;
    GtkWidget *widget = NULL;
    gchar * glade_file = NULL;
    gchar * logo_path = NULL;
    gchar * logo_g_path = NULL;
    GdkPixbuf * gear_logo_g = NULL;

    self = XMALLOC( gs_main_window_t, 1 );

    /* Iniciando ponteiros */
    self->core = NULL;
    self->ww_main = NULL;
    self->dg_about = NULL;
    self->et_serial_path = NULL;
    self->tb_connect = NULL;
    self->ta_buttons_area = NULL;
    self->sb_speed = NULL;
    self->tb_dribble = NULL;

    glade_file = gs_utils_get_file_inside_data( argv,
						"gs_main_window.glade");
    /* Where is the .glade file for this object? */
    if( (builder = glade_xml_new( glade_file,
				  NULL,
				  NULL )) == NULL )
    {
	xerror_fatal("Nao consegui achar os arquivos de descricao "
		     "da interface. Tem certeza que voce nao saiu "
		     "andando com o executavel por ai?\n"
		     "Assim fica um pouco mais complicado...\n");		
    }
    g_free(glade_file);

    /* Gear Logo */
    logo_path = gs_utils_get_file_inside_data( argv,
					       "gear_logo.png");
    if( (self->gear_logo = gdk_pixbuf_new_from_file( logo_path,
						     NULL )) == NULL )
    {
	xerror_warning("Nao consegui abrir o logo do GEAR ");
    }
    g_free(logo_path);

    self->ww_main = GTK_WINDOW(glade_xml_get_widget( builder,
						     "ww_main" ));
    /* Gear G Logo */
    logo_g_path = gs_utils_get_file_inside_data( argv,
						 "gear_logo_g.png");
    if( (gear_logo_g = gdk_pixbuf_new_from_file( logo_g_path,
						 NULL )) == NULL )
    {
	xerror_warning("Nao consegui abrir o logo G do GEAR ");
    }
    g_free(logo_g_path);

    gtk_window_set_default_icon( gear_logo_g );
    gtk_window_set_title( self->ww_main,
			  "GEARSerial" );
    
    /* Creating the interface */    
    g_signal_connect( self->ww_main,
		      "delete-event",
		      G_CALLBACK( std_delete_event_handler ),
		      self );

    gtk_window_set_default_size( GTK_WINDOW(self->ww_main),
				 400,
				 200 );

    /* widget: mi_quit */
    action1 = GTK_MENU_ITEM( glade_xml_get_widget( builder,
						   "mi_quit" ));
    g_signal_connect( G_OBJECT(action1),
		      "activate",
		      G_CALLBACK( std_button_handler ),
		      self );
    g_object_set_data( G_OBJECT( action1 ),
		       "handler",
		       GUINT_TO_POINTER( MI_QUIT ) );

    /* widget:bt_up*/
    widget = GTK_WIDGET( glade_xml_get_widget( builder,
					       "bt_up" ));
    g_signal_connect( G_OBJECT( widget ),
		      "clicked",
        	      G_CALLBACK( std_button_handler),
		      self );
    g_object_set_data( G_OBJECT( widget ),
		       "handler",
		       GINT_TO_POINTER( BT_UP ) );

    /* widget:bt_down*/
    widget = GTK_WIDGET( glade_xml_get_widget( builder,
					       "bt_down" ));
    g_signal_connect( G_OBJECT( widget ),
		      "clicked",
        	      G_CALLBACK( std_button_handler),
		      self );
    g_object_set_data( G_OBJECT( widget ),
		       "handler",
		       GINT_TO_POINTER( BT_DOWN ) );

    /* widget:bt_turn_left*/
    widget = GTK_WIDGET( glade_xml_get_widget( builder,
					       "bt_turn_left" ));
    g_signal_connect( G_OBJECT( widget ),
		      "clicked",
        	      G_CALLBACK( std_button_handler),
		      self );
    g_object_set_data( G_OBJECT( widget ),
		       "handler",
		       GINT_TO_POINTER( BT_TURN_LEFT ) );

    /* widget:bt_turn_right*/
    widget = GTK_WIDGET( glade_xml_get_widget( builder,
					       "bt_turn_right" ));
    g_signal_connect( G_OBJECT( widget ),
		      "clicked",
        	      G_CALLBACK( std_button_handler),
		      self );
    g_object_set_data( G_OBJECT( widget ),
		       "handler",
		       GINT_TO_POINTER( BT_TURN_RIGHT ) );

    /* widget:bt_stop*/
    widget = GTK_WIDGET( glade_xml_get_widget( builder,
					       "bt_stop" ));
    g_signal_connect( G_OBJECT( widget ),
		      "clicked",
        	      G_CALLBACK( std_button_handler),
		      self );
    g_object_set_data( G_OBJECT( widget ),
		       "handler",
		       GINT_TO_POINTER( BT_STOP ) );

    /* widget:mi_about */
    widget = GTK_WIDGET( glade_xml_get_widget( builder,
					       "mi_about" ));
    g_signal_connect( G_OBJECT( widget ),
		      "activate",
        	      G_CALLBACK( std_button_handler),
		      self );
    g_object_set_data( G_OBJECT( widget ),
		       "handler",
		       GINT_TO_POINTER( MI_ABOUT ) );

    /* widget:et_serial_path */
    self->et_serial_path = GTK_ENTRY(
	glade_xml_get_widget( builder,
			      "et_serial_path" ));
    gtk_entry_set_text( self->et_serial_path,
			"/dev/ttyS0");

    
    
    /* widget:tb_connect*/
    self->tb_connect = GTK_TOGGLE_BUTTON( glade_xml_get_widget( builder,
								"tb_connect" ));
    g_signal_connect( G_OBJECT( self->tb_connect ),
		      "toggled",
        	      G_CALLBACK( std_button_handler),
		      self );
    g_object_set_data( G_OBJECT( self->tb_connect ),
		       "handler",
		       GINT_TO_POINTER( TB_CONNECT ) );

    /* widget:ta_buttons_area */
    self->ta_buttons_area = GTK_TABLE(
	glade_xml_get_widget( builder,
			      "ta_buttons_area" ));
    gtk_widget_set_sensitive( GTK_WIDGET(self->ta_buttons_area),
			      FALSE );

    /* widget:sb_speed */
    self->sb_speed = GTK_SPIN_BUTTON(
	glade_xml_get_widget( builder,
			      "sb_speed" ));

    /* widget:bt_kick*/
    widget = GTK_WIDGET( glade_xml_get_widget( builder,
					       "bt_kick" ));
    g_signal_connect( G_OBJECT( widget ),
		      "clicked",
        	      G_CALLBACK( std_button_handler),
		      self );
    g_object_set_data( G_OBJECT( widget ),
		       "handler",
		       GINT_TO_POINTER( BT_KICK ) );

    /* widget:tb_dribble*/
    self->tb_dribble = GTK_TOGGLE_BUTTON( glade_xml_get_widget( builder,
								"tb_dribble" ));
    g_signal_connect( G_OBJECT( self->tb_dribble ),
		      "toggled",
        	      G_CALLBACK( std_button_handler),
		      self );
    g_object_set_data( G_OBJECT( self->tb_dribble ),
		       "handler",
		       GINT_TO_POINTER( TB_DRIBBLE ) );
    
    return self;
}

/* Standard Button Handler */
static void
std_button_handler( GtkButton *button,
		    gpointer user_data )
{
    gs_main_window_t *self =
	(gs_main_window_t*) user_data;

    enum gs_main_window_buttons handler = (enum gs_main_window_buttons)
	g_object_get_data( G_OBJECT( button ), "handler" );

    switch( handler )
    {
    case TB_DRIBBLE:
    {
	if( gtk_toggle_button_get_active(self->tb_dribble) )
	{
	    gs_core_robot_dribble_enable( self->core,
					  1 );
	}
	else
	{
	    gs_core_robot_dribble_enable( self->core,
					  0 );
	}
	break;
    }
    case BT_KICK:
    {
	gs_core_robot_kick( self->core );
	break;
    }
    case TB_CONNECT:
    {
	if( gtk_toggle_button_get_active(self->tb_connect) )
	{
	    self->core = gs_core_new(
		(char*)gtk_entry_get_text(self->et_serial_path) );
	    
	    if( self->core != NULL )
		gtk_widget_set_sensitive( GTK_WIDGET(self->ta_buttons_area),
					  TRUE );
	    else
		gtk_toggle_button_set_active( self->tb_connect,
					      FALSE );
	}
	else
	{
	    if( self->core != NULL )
		gs_core_destroy( self->core );
	    self->core = NULL;
	    gtk_widget_set_sensitive( GTK_WIDGET(self->ta_buttons_area),
				      FALSE );
	}
	break;
    }
    case MI_ABOUT:
    {
	const gchar *authors[] =
	    {"Diogo F. S. Ramos <diogo.ramos@usp.br>",
	     NULL};
	const gchar copyright[] =
	    {"Copyright \xc2\xa9 2008 GEAR"
	     " - Grupo de Estudos Avançados em Robótica\n"};
	const gchar comments[] =
	    {"Comandando robôs através da Serial"};
	const gchar website[] =
	    {"http://www.sel.eesc.usp.br/gear"};
	const gchar license[] =						
	    {"This program is free software: you can redistribute it and/or modify " 
	     "it under the terms of the GNU General Public License as published by " 
	     "the Free Software Foundation, either version 3 of the License, or (at " 
	     "your option) any later version.\n\n"				
	     "This program is distributed in the hope that it will be useful, but " 
	     "WITHOUT ANY WARRANTY; without even the implied warranty of "	
	     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU " 
	     "General Public License for more details.\n\n"			
	     "You should have received a copy of the GNU General Public License " 
	     "along with this program.  If not, see <http://www.gnu.org/licenses/>."};
	
	gtk_show_about_dialog(
	    self->ww_main,
	    "authors", authors,
	    "program-name", "GEARSerial",
	    "version", PACKAGE_VERSION,
	    "comments", comments,
	    "website", website,
	    "copyright", copyright,
	    "license", license,
	    "wrap-license", TRUE,
	    "logo", self->gear_logo,
	    NULL );
	break;
    }
    case MI_QUIT:
    {
	gs_main_window_quit( self );
	break;
    }
    case BT_UP:
    {
	gint speed = gtk_spin_button_get_value_as_int( self->sb_speed );
	gs_core_set_robot_forward( self->core,
				   (char) speed);
	break;
    }
    case BT_DOWN:
    {
	gint speed = gtk_spin_button_get_value_as_int( self->sb_speed );
	gs_core_set_robot_backward( self->core,
				    (char) speed);
	break;
    }
    case BT_TURN_LEFT:
    {
	gint speed = gtk_spin_button_get_value_as_int( self->sb_speed );
	gs_core_set_robot_turn_left( self->core,
				     (char) speed);
	break;
    }
    case BT_TURN_RIGHT:
    {
	gint speed = gtk_spin_button_get_value_as_int( self->sb_speed );
	gs_core_set_robot_turn_right( self->core,
				      (char) speed);
	break;
    }
    case BT_STOP:
    {
	gs_core_set_robot_stop( self->core );
	break;
    }
    }
}

/** Última função chamada antes de sair.
 *
 * @param *self Objeto Main Window
 */
static void
gs_main_window_quit( gs_main_window_t * self )
{
    if( self->core )
	gs_core_destroy( self->core );
    
    gtk_main_quit();
}

static gint
std_delete_event_handler (GtkWidget   *widget,
			  GdkEventAny *event,
			  gpointer     user_data)
{
    gs_main_window_quit( (gs_main_window_t*) user_data );
    return TRUE;
}
